package cn.northsea.common;

import java.util.*;

public class CollaborativeFilteringJobRecommendation {

//     用户-岗位评分矩阵，示例数据
//    private static Map<String, Map<String, Integer>> userJobRatings = new HashMap<>();
//
//    static {
//        // 初始化数据
//        Map<String, Integer> jobRatingsUser1 = new HashMap<>();
//        jobRatingsUser1.put("Developer", 5);
//        jobRatingsUser1.put("Designer", 3);
//        jobRatingsUser1.put("Manager", 2);
//        userJobRatings.put("User1", jobRatingsUser1);
//
//        Map<String, Integer> jobRatingsUser2 = new HashMap<>();
//        jobRatingsUser2.put("Developer", 4);
//        jobRatingsUser2.put("Product Manager", 4);
//        jobRatingsUser2.put("Manager", 1);
//        userJobRatings.put("User2", jobRatingsUser2);
//
//        Map<String, Integer> jobRatingsUser3 = new HashMap<>();
//        jobRatingsUser3.put("Developer", 5);
//        jobRatingsUser3.put("Designer", 4);
//        jobRatingsUser3.put("QA", 3);
//        userJobRatings.put("User3", jobRatingsUser3);
//
//        // 可以继续添加更多用户和岗位评分
//    }

    // 计算皮尔逊相关系数
    private static double pearsonCorrelation(Map<String, Integer> ratings1, Map<String, Integer> ratings2) {
        Set<String> commonItems = new HashSet<>(ratings1.keySet());
        commonItems.retainAll(ratings2.keySet());

        int n = commonItems.size();

        if (n == 0) return 0;

        double sum1 = 0, sum2 = 0, sum1Sq = 0, sum2Sq = 0, pSum = 0;

        for (String item : commonItems) {
            int r1 = ratings1.get(item);
            int r2 = ratings2.get(item);

            sum1 += r1;
            sum2 += r2;
            sum1Sq += Math.pow(r1, 2);
            sum2Sq += Math.pow(r2, 2);
            pSum += r1 * r2;
        }

        double num = pSum - (sum1 * sum2 / n);
        double den = Math.sqrt((sum1Sq - Math.pow(sum1, 2) / n) * (sum2Sq - Math.pow(sum2, 2) / n));
        if (den == 0) return 0;

        return num / den;
    }

    // 获取相似用户
    private static List<Map.Entry<String, Double>> getSimilarUsers(String targetUser, int k,HashMap<String, Map<String, Integer>> map) {
        List<Map.Entry<String, Double>> similarities = new ArrayList<>();

        for (Map.Entry<String, Map<String, Integer>> entry : map.entrySet()) {
            String user = entry.getKey();
            if (!user.equals(targetUser)) {
                double similarity = pearsonCorrelation(map.get(targetUser), entry.getValue());
                similarities.add(new AbstractMap.SimpleEntry<>(user, similarity));
            }
        }

        Collections.sort(similarities, (e1, e2) -> Double.compare(e2.getValue(), e1.getValue()));

        return similarities.subList(0, k);
    }

    // 推荐岗位
    public static List<Map.Entry<String, Double>> recommendJobs(String targetUser, int k,HashMap<String, Map<String, Integer>> map) {
        Map<String, Double> scores = new HashMap<>();
        System.out.println(map);
        List<Map.Entry<String, Double>> similarUsers = getSimilarUsers(targetUser, 10,map); // 获取前5个相似用户

        for (Map.Entry<String, Double> userSimilarity : similarUsers) {
            String similarUser = userSimilarity.getKey();
            double similarity = userSimilarity.getValue();

            for (Map.Entry<String, Integer> jobRating : map.get(similarUser).entrySet()) {
                String job = jobRating.getKey();
                int rating = jobRating.getValue();

                if (!map.get(targetUser).containsKey(job)) { // 如果目标用户没有评过分
                    scores.put(job, scores.getOrDefault(job, 0.0) + similarity * rating);
                }
            }
        }

        List<Map.Entry<String, Double>> sortedScores = new ArrayList<>(scores.entrySet());
        Collections.sort(sortedScores, (e1, e2) -> Double.compare(e2.getValue(), e1.getValue()));

        return sortedScores.subList(0, k);
    }

//    public static void main(String[] args) {
//        String targetUser = "User1";
//        int k = 2; // 推荐前3个岗位
//
//        List<Map.Entry<String, Double>> recommendations = recommendJobs(targetUser, k);
//
//        System.out.println("Recommendations for " + targetUser + ":");
//        for (Map.Entry<String, Double> recommendation : recommendations) {
//            System.out.println(recommendation.getKey() + ": " + recommendation.getValue());
//        }
//    }
}
